﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Arch.Data;
using System.Data;
using System.Data.Objects;
using Microsoft.Practices.Unity;
using System.Data.Metadata.Edm;
using Arch.Common.Reflection;

namespace Arch.EF.Data
{
    public class EntityRepository<T> : ArchRepository<T> where T : class, new()
    {
        [Dependency]
        public virtual ObjectContext Context { get; set; }

        public string DefaultIncludes { get; set; }

        private EntitySetBase _entitySetBase;
        public EntitySetBase EntitySetBase
        {
            get { return _entitySetBase ?? (_entitySetBase = Context.GetEntitySet<T>()); }
        }

        protected virtual ObjectQuery<T> Set { get { return Context.CreateQuery<T>(EntitySetBase.GetFullName()); } }

        public override IQueryable<T> GetQuery()
        {
            ObjectQuery<T> q = Set;
            if (DefaultIncludes != null)
            {
                q = (DefaultIncludes).Split(',').Aggregate(q, (current, include) => 
                    current.Include(include.Trim()));
            }
            return q;
        }

        public override T Load(object id)
        {
            if (!(id is EntityKey)) id = Context.CreateEntityKey<T>(id);
            return Context.GetObjectByKey(id as EntityKey) as T;
        }

        public override T Create(T entity)
        {
            Context.AddObject(EntitySetBase.GetFullName(), entity);
            return entity;
        }

        public override T Delete(T entity)
        {
            Context.DeleteObject(entity);
            return entity;
        }

        public override T Update(T entity)
        {
            return entity;
        }

        public override T New()
        {
            return Context.CreateObject<T>();
        }

        public override T Attach(T entity, bool modified = false)
        {
            Context.AttachTo(EntitySetBase.GetFullName(), entity);
            if (modified)
            {
                Context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
            }
            return entity;
        }

        public override T Detach(T entity)
        {
            Context.Detach(entity);
            return entity;
        }
    }

    public class EntityRepository : ArchRepository
    {
        [Dependency]
        public ObjectContext Context { get; set; }

        public override void SaveChanges()
        {
            Context.SaveChanges();
        }
    }
}
